package com.hmall.item.controller;


import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hmall.common.domain.PageDTO;
import com.hmall.item.domain.dto.ItemDTO;
import com.hmall.item.domain.po.Item;
import com.hmall.item.domain.po.ItemDoc;
import com.hmall.item.domain.query.ItemPageQuery;
import com.hmall.item.service.IItemService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Api(tags = "搜索相关接口")
@RestController
@RequestMapping("/search")
@RequiredArgsConstructor
public class SearchController {

    private final IItemService itemService;

    @Autowired
    private RestHighLevelClient client;

//    @ApiOperation("搜索商品")
//    @GetMapping("/list")
//    public PageDTO<ItemDTO> search(ItemPageQuery query) {
//        // 分页查询
//        Page<Item> result = itemService.lambdaQuery()
//                .like(StrUtil.isNotBlank(query.getKey()), Item::getName, query.getKey())
//                .eq(StrUtil.isNotBlank(query.getBrand()), Item::getBrand, query.getBrand())
//                .eq(StrUtil.isNotBlank(query.getCategory()), Item::getCategory, query.getCategory())
//                .eq(Item::getStatus, 1)
//                .between(query.getMaxPrice() != null, Item::getPrice, query.getMinPrice(), query.getMaxPrice())
//                .page(query.toMpPage("update_time", false));
//        // 封装并返回
//        return PageDTO.of(result, ItemDTO.class);
//    }

    @ApiOperation("搜索商品")
    @GetMapping("/list")
    public PageDTO search(ItemPageQuery query) throws IOException {
        query.setIsAsc(true);

        SearchRequest request = new SearchRequest("items");
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if(!StrUtil.isBlank(query.getKey()))
            queryBuilder.must(QueryBuilders.matchQuery("name", query.getKey()));
        if (!StrUtil.isBlank(query.getBrand()))
            queryBuilder.must(QueryBuilders.termQuery("brand", query.getBrand()));
        if (!StrUtil.isBlank(query.getCategory()))
            queryBuilder.must(QueryBuilders.termQuery("category", query.getCategory()));
        if (query.getMaxPrice() != null && query.getMinPrice() != null)
            queryBuilder.must(QueryBuilders.rangeQuery("price").from(query.getMinPrice()).to(query.getMaxPrice()));
//        request.source().sort(StrUtil.isBlank(query.getSortBy()) ?"updateTime":query.getSortBy(), query.getIsAsc()? SortOrder.ASC: SortOrder.DESC);
//        request.source().query(queryBuilder);
        // 使用 function_score 查询调整评分
        FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(
                queryBuilder,
                new FunctionScoreQueryBuilder.FilterFunctionBuilder[] {
                        new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                                QueryBuilders.termQuery("isAD", true),
                                ScoreFunctionBuilders.weightFactorFunction(100000f)
                        )
                }
        ).scoreMode(FunctionScoreQuery.ScoreMode.SUM);


        request.source().query(functionScoreQueryBuilder);
        request.source().from(query.getPageNo()).size(query.getPageSize());
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);

        long value = search.getHits().getTotalHits().value;
        // 2.遍历结果数组
        SearchHit[] hits = search.getHits().getHits();
        List<ItemDoc> list=new ArrayList<>();
        for (SearchHit hit : hits){
            String source = hit.getSourceAsString();
            ItemDoc item = JSONUtil.toBean(source, ItemDoc.class);
            list.add(item);
        }
        PageDTO<ItemDoc> page = new PageDTO<>();
        page.setTotal(value);
        page.setList(list);
        page.setPages(Long.valueOf(query.getPageNo().toString()));
        return page;
    }
}
